<?php
/*
 * @Desc 构建控制器，模型类
 * @Auth Sang
 * @Date 2015-04-22 23:05:09
 **/
namespace Act\Os;
class SysBuild extends \Lib\Action {
    public function doGet() {
        // 取得所有表
        $resultTables = model()->getTables();
        $tables = [];
        foreach ($resultTables as $key => $table) {
            $modName = preg_replace('/^adm_/', '', $table);
            $modName = preg_replace_callback('/_(\w{1})/', function ($matches) {
                return strtoupper($matches[1]);
            }
            , $modName);
            $modName = ucwords($modName);
            $mod_paths = [DOCUMENT_ROOT . 'Mod/' . $modName . '.php', FRAME_ROOT . 'mod/' . $modName . '.php'];
            $mod_exists = false;
            foreach ($mod_paths as $key => $mod_path) {
                if (is_file($mod_path)) {
                    $mod_exists = true;
                    break;
                }
            }
            $tables[] = ['table_name' => $table, 'mod_name' => $modName, 'exists' => $mod_exists];
        }
        echo <<<eof
<!DOCTYPE html>
<html>
<head>
  <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
  <link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css">
  <link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap-theme.min.css">
  <script src="http://apps.bdimg.com/libs/bootstrap/3.3.4/js/bootstrap.min.js"></script>
  <title></title>
</head>
<body>

<style>
  .act_btn{position:absolute;right:170px;top:6px;width:60px;color:#ffffff;height:30px;line-height:30px;text-align:center;font-weight:bold;cursor:pointer;background:#4B95B5;border-radius:5px;}
  .act_btn:last-child{right:107px;}
  .input-prepend .field-name{width:100px;text-align: right;}
  .input-prepend .add-on{margin-left:0;}
</style>
<div class="well">
    <ul class="nav nav-tabs">
      <li class="active"><a href="#model" data-toggle="tab">构建模型类</a></li>
    </ul>
    <div id="myTabContent" class="tab-content">
      <div class="tab-pane active in" id="model">
      <form method="post" action="" class="form-horizontal">
eof;
        foreach ($tables as $table):
            $created = $table['exists'] ? '<font color="red">已创建|重新创建</font>' : '创建模型类';
            echo <<<eof
          <div class="control-group" style="margin:10px">
            <div class="input-prepend input-append">
              <span class="add-on">表名</span>
              <span class="input-large uneditable-input table_name">{$table['table_name']}</span>
              <div class="space"></div>
              <span class="add-on">模型类名</span>
              <input type="text" class="input-large mod_name" value="{$table['mod_name']}">
            <button type="button" class="btn btn-primary">{$created}</button>
            </div>
          </div>
          <hr style="border-color:#999999">
eof;

        endforeach;
        echo <<<eof
      </form>
      <script>
      $('#model .btn').click(function(){
        var modName = \$(this).siblings('.mod_name').val(),
          tableName = \$(this).siblings('.table_name').text();
        var me = this;
        if(\$('#codeRow-'+modName).length){
          return;
        }
        \$.ajax({
          url:'/os/sysBuild?act=createMod',
          dataType:'json',
          type:'post',
          data:{mod_name:modName,table_name:tableName},
          success:function(result){
            if(!result.error){
              var textarea = \$('<div class="control-group" id="codeRow-'+modName+'" style="position:relative"><textarea id="codeTextarea-'+modName+'" class="span11" style="height:500px;width:700px">'+result.code+'</textarea><span id="act_btn-'+modName+'" class="act_btn js-copy" data-clipboard-target="codeTextarea-'+modName+'">复制</span>&nbsp;<span class="act_btn" onclick="$(this).parent().remove()">关闭</span></div>');
              \$(me).parent().parent().after(textarea);
            }else{
              alert(result.msg);
            }
          }
        });
      });
      </script>
    </div>
  </div>
</div>
</div>
</body>
</html>
eof;

    }
    public function doPost() {
        if (in_array($this->act, ['createMod', 'createAct'])) {
            return call_user_func([$this, $this->act]);
        }
    }
    private function createMod() {
        $table_name = post('table_name', '', 'strip_tags,trim');
        $mod_name = post('mod_name', '', 'strip_tags,trim');
        if (check_not_empty($table_name, $mod_name) == false) {
            return $this->jsonError('缺少参数');
        }
        try {
            $code = $this->createCode($mod_name, $table_name);
            return $this->json(['success' => 1, 'code' => $code]);
        }
        catch(Exception $e) {
            return $this->jsonError('发生错误，可能表不存在');
        }
    }
    private function createCode($mod_name, $table_name) {
        $mod = model();
        $fields = $mod->db->getFields($table_name);
        $pri_key = '';
        foreach ($fields as $key => $info) {
            if ($info['primary']) {
                $pri_key = $key;
                break;
            }
        }
        !$pri_key && $pri_key = current(array_keys($fields));
        //生成数据验证
        $validate_str = $update_validate_str = '
        $validator = new \Lib\Validator($data);
        $validator->setRules([';
        foreach ($fields as $field) {
            if ($field['primary']) {
                continue;
            }
            $field_filter = '';
            switch (true) {
                case strstr($field['type'], 'bigint'):
                    $field_filter = 'longint';
                case strstr($field['type'], 'int'):
                    $field_filter = 'absint';
                    break;

                case strstr($field['type'], 'char'):
                case strstr($field['type'], 'text'):
                case strstr($field['type'], 'blob'):
                    $field_filter = 'strip_tags,trim';
                    break;

                case strstr($field['type'], 'decimal'):
                    $field_filter = 'floatval,abs';
                    break;

                case strstr($field['type'], 'double'):
                case strstr($field['type'], 'float'):
                    $field_filter = 'floatval';
                    break;

                default:
                    $field_filter = 'trim';
                    break;
            }
            $validate_str.= "
            '{$field['name']}' => ['required'=>true,'validate'=>'{$field_filter}'],";
            $update_validate_str.= "
            '{$field['name']}' => ['validate'=>'{$field_filter}'],";
        }
        $validate_str.= '
        ])';
        $update_validate_str.= '
        ])';
        $validate_str.= '->setMessages([';
        $update_validate_str.= '->setMessages([';
        foreach ($fields as $field) {
            if ($field['primary']) {
                continue;
            }
            $field_name = !empty($field['comment']) ? $field['comment'] : $field['name'];
            $validate_str.= "
            '{$field['name']}' => ['required'=>'{$field_name}不能为空','validate'=>'{$field_name}填写不正确'],";
            $update_validate_str.= "
            '{$field['name']}' => ['validate'=>'{$field_name}填写不正确'],";
        }
        $validate_str.= '
        ]);
    ';
        $update_validate_str.= '
        ]);
    ';
        $validate_str.= '
        $data = $validator->validate();
        if(!$data){
            $this->error = $validator->getError();
            return false;
        }
        ';
        $update_validate_str.= '
        $data = $validator->validate();
        if(!$data){
            $this->error = $validator->getError();
            return false;
        }
    ';
        // 生成数据验证结束
        $date = date('Y-m-d H:i:s');
        $str = <<<EOT
<?php
/**
* @Auth By AutoCreateCode
* @Desc {$mod_name}类
* @Date {$date}
*/
namespace App\Mod;
use Lib\Model;
class {$mod_name} extends Model{
    /**
    * 插入数据
    * @access public
    * @param Array \$data 要插入的数据
    * @return Bool
    */
    public function add{$mod_name}(\$data){
        if(empty(\$data) || !is_array(\$data)){
            return false;
        }
        {$validate_str}
        return \$this->insert(\$data);
    }

    /**
    * 根据ID删除多条记录
    * @access public
    * @param Mix \$id 要删除的ID，可为数组，也可用逗号用隔
    * @return Bool
    */
    public function del{$mod_name}(\$id){
        if(empty(\$id) || (!is_numeric(\$id) && !is_array(\$id))){
            return false;
        }
        \$ids = is_array(\$id) ? join(',',\$id) : \$id;
        return \$this->where("{$pri_key} in({\$ids})")->delete();
    }

    /**
    * 根据ID修改记录
    * @access public
    * @param Int \$id 要修改的ID
    * @param Array \$data 要修改的数据
    * @return Bool
    */
    public function update{$mod_name}(\$id,\$data){
        if(empty(\$id) || (!is_numeric(\$id) && !is_array(\$id)) || empty(\$data) || !is_array(\$data)){
            return false;
        }
        {$update_validate_str}
        \$ids = is_array(\$id) ? join(',',\$id) : \$id;
        return \$this->where("{$pri_key} in({\$ids})")->update(\$data);
    }

    /**
    * 根据ID获取单条记录
    * @access public
    * @param Int \$id 要查询的ID
    * @param String \$fields 要返回的字段
    * @return Array
    */
    public function get{$mod_name}ById(\$id,\$fields="*"){
        if(empty(\$id) || !is_numeric(\$id)){
            return false;
        }
        return \$this->where("{$pri_key}={\$id}")->fields(\$fields)->fetch();
    }

    /**
    * 根据多个ID获取多条记录
    * @access public
    * @param Mix \$ids 要查询的ID,可为数组，也可以用逗号分隔
    * @param String \$fields 要返回的字段
    * @return Array
    */
    public function get{$mod_name}ByIds(\$ids,\$fields="*"){
        if(!is_array(\$ids)){
            \$ids = explode(',',\$ids);
        }
        \$ids = join(',',\$ids);
        return \$this->where("{$pri_key} in(\$ids)")->order("find_in_set({$pri_key},'{\$ids}')")->fields(\$fields)->select();
    }

    /**
    * 根据SQL条件查询记录
    * @access public
    * @param String \$condition 查询条件
    * @param Int \$offset 偏移量
    * @param Int \$size 返回条数
    * @param String \$order 排序
    * @param String \$fields 要返回的字段
    * @return Mix Array
    */
    public function search(\$condition,\$offset=0,\$size=20,\$order='{$pri_key} desc',\$fields='*'){
        return \$this->fields(\$fields)->where(\$condition)->order(\$order)->limit(\$offset,\$size)->select();
    }

    /**
    * 根据条件返回记录数
    * @access public
    * @param String \$condition 查询条件
    * @return Int
    */
    public function searchCount(\$condition){
        return \$this->where(\$condition)->count();
    }
}
EOT;
        return $str;
    }
}

